grammar ArkcubeRule;

@lexer::members {
public static final int NEWLINE = 1;
public static final int COMMENTS = 2;
}

program: singleState* EOF;

singleState: assignState | expressionState | feederState;

// 计算规则赋值
assignState: shorthand '=' (Identifier ':')? expr ';';

// 表达式，如Scope({'所有年'.leaves});skipcheck; Feeders; EndScope;
expressionState: (functionCall | Identifier) ';';

// Feeder
feederState
    : shorthand '=>' shorthand ';'
    | shorthand '=>' functionCall ';'
;

// 冒号运算符外层是大括号{‘01月’:'12月'}，表示ELEMENT_ARRAY
// 冒号运算符外层是方括号或圆括号[‘期间’:'12月']、SUM(‘期间’:'12月')，表示维度声明
expr
    : Number                                                            # Number
    | StringLiteral                                                     # StringLiteral
    | BooleanLiteral                                                    # BooleanLiteral
    | Identifier                                                        # Name
    | '!' dim                                                           # Target
    | expr '.' Identifier                                               # MemberRange
    | dim ':' expr                                                      # DimColon
    | '{' arguments '}'                                                 # MemberSet
    | shorthand                                                         # ShorthandMethod
    | left = expr op = '^' right = expr                                 # PowerLike
    | op = ('+'|'-'|'~') right = expr                                   # PrefixExpression
    | left = expr op = ('*'|'/'|'\\') right = expr                      # MultiplyLike
    | left = expr op = ('+'|'-') right = expr                           # PlusLike
    | left = expr op = '|' right = expr                                 # ListLike
    | left = expr op = ('='|'<>'|'>'|'>='|'<'|'<='|'@='|'@<>'|'@>'|'@>='|'@<'|'@<=') right = expr        # CompareLike
    | left = expr op = ('%'|'&') right = expr                           # LogicLike
    | '(' expr ')'                                                      # PriorityExpression
    | functionCall                                                      # FunctionApply
;

arguments: expr (',' expr)*;
shorthand: '[' arguments ']';
functionCall: Identifier '(' arguments? ')';

dim: Identifier | StringLiteral;


Number                              : Integer ('.' Digit+)?;
StringLiteral                       : Str1 | Str2;
BooleanLiteral                      : 'true' | 'false';

Plus                                : '+';      // 正号和加号
Minus                               : '-';      // 负号和减号
Star                                : '*';      // 乘
Div                                 : '/';      // 除
Div2                                : '\\';     // 除，除0得0
Caret                               : '^';      // 幂，注意tabase的幂运算是左结合
Or                                  : '|';      // 字符拼接
Comma                               : ',';      // 逗号
Dot                                 : '.';      // 点
Colon                               : ':';      // 冒号
Sharp                               : '#';      // 注释
Not                                 : '!';      // 反向引用
And                                 : '&';      // 且
Percent                             : '%';      // 或
Tilde                               : '~';      // 非
Equal                               : '=';      // 赋值和等于
NotEqual                            : '<>';     // 不等于
Greater                             : '>';      // 大于
GreaterEqual                        : '>=';     // 大于等于
Less                                : '<';      // 小于
LessEqual                           : '<=';     // 小于等于
StrEqual                            : '@=';     // 文本相等
StrNotEqual                         : '@<>';     // 文本不等于
StrGreater                          : '@>';      // 文本大于
StrGreaterEqual                     : '@>=';     // 文本大于等于
StrLess                             : '@<';      // 文本小于
StrLessEqual                        : '@<=';     // 文本小于等于
Feed                                : '=>';     // Feeder
SingleQuote                         : '\'';     // 单引号
Semi                                : ';';      // 分号
LeftParen                           : '(';      // 左括号
RightParen                          : ')';      // 右括号
LeftBracket                         : '[';      // 左方括号
RightBracket                        : ']';      // 右方括号
LeftBrace                           : '{';      // 左大括号
RightBrace                          : '}';      // 右大括号


fragment Str1    : '"' SChar* '"';
fragment Str2    : '\'' SChar2* '\'';
fragment SChar   :   ~["] | '\\"';
fragment SChar2  :   ~['] | '\\\'';
fragment Integer : Zero+ | [1-9] Digit*;
fragment Digit   : Zero | [1-9];
fragment Zero    : [0];

Identifier                          : ~[ .%^=()&[\]'*@:,{}\\"!><|+\-?;/~\r\n\t]+;

NewLine             : ('\r'? '\n' | '\r')+ -> channel(1);
WhiteSpace          : [ \t\p{Z}]+ -> skip;
LineComment         : '#' .*? '\n' -> channel(2);
